home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / cc / sprite / RCS / out-sparc.c,v < prev    next >
Encoding:
Text File  |  1990-02-07  |  53.2 KB  |  2,041 lines

  1. head     1.3;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.3
  10. date     90.02.06.21.37.14;  author rab;  state Exp;
  11. branches ;
  12. next     1.2;
  13.  
  14. 1.2
  15. date     90.01.12.09.40.53;  author rab;  state Exp;
  16. branches ;
  17. next     1.1;
  18.  
  19. 1.1
  20. date     89.12.15.12.40.46;  author rab;  state Exp;
  21. branches ;
  22. next     ;
  23.  
  24.  
  25. desc
  26. @@
  27.  
  28.  
  29. 1.3
  30. log
  31. @Fixed bug in referencing array of double.
  32. @
  33. text
  34. @/* Subroutines for insn-output.c for Sun SPARC.
  35.    Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
  36.    Contributed by Michael Tiemann (tiemann@@mcc.com)
  37.  
  38. This file is part of GNU CC.
  39.  
  40. GNU CC is free software; you can redistribute it and/or modify
  41. it under the terms of the GNU General Public License as published by
  42. the Free Software Foundation; either version 1, or (at your option)
  43. any later version.
  44.  
  45. GNU CC is distributed in the hope that it will be useful,
  46. but WITHOUT ANY WARRANTY; without even the implied warranty of
  47. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  48. GNU General Public License for more details.
  49.  
  50. You should have received a copy of the GNU General Public License
  51. along with GNU CC; see the file COPYING.  If not, write to
  52. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  53.  
  54. /* Global variables for machine-dependend things.  */
  55.  
  56. /* This should go away if we pass floats to regs via
  57.    the stack instead of the frame, and if we learn how
  58.    to renumber all the registers when we don't do a save (hard!).  */
  59. extern int frame_pointer_needed;
  60.  
  61. static rtx find_addr_reg ();
  62.  
  63. rtx next_real_insn_no_labels ();
  64.  
  65. /* Return non-zero only if OP is a register of mode MODE,
  66.    or const0_rtx.  */
  67. int
  68. reg_or_0_operand (op, mode)
  69.      rtx op;
  70.      enum machine_mode mode;
  71. {
  72.   return (op == const0_rtx || register_operand (op, mode));
  73. }
  74.  
  75. /* Return non-zero if this pattern, can be evaluated safely, even if it
  76.    was not asked for.  */
  77. int
  78. safe_insn_src_p (op, mode)
  79.      rtx op;
  80.      enum machine_mode mode;
  81. {
  82.   /* Just experimenting.  */
  83.  
  84.   /* No floating point src is safe if it contains an arithmetic
  85.      operation, since that operation may trap.  */
  86.   switch (GET_CODE (op))
  87.     {
  88.     case CONST_INT:
  89.     case LABEL_REF:
  90.     case SYMBOL_REF:
  91.     case CONST:
  92.       return 1;
  93.  
  94.     case REG:
  95.       return 1;
  96.  
  97.     case MEM:
  98.       return CONSTANT_ADDRESS_P (XEXP (op, 0));
  99.  
  100.       /* We never need to negate or complement constants.  */
  101.     case NEG:
  102.       return (mode != SFmode && mode != DFmode);
  103.     case NOT:
  104.       return 1;
  105.  
  106.     case COMPARE:
  107.     case MINUS:
  108.     case PLUS:
  109.       return (mode != SFmode && mode != DFmode);
  110.     case AND:
  111.     case IOR:
  112.     case XOR:
  113.     case LSHIFT:
  114.     case ASHIFT:
  115.     case ASHIFTRT:
  116.     case LSHIFTRT:
  117.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  118.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  119.     return 0;
  120.       return 1;
  121.  
  122.     default:
  123.       return 0;
  124.     }
  125. }
  126.  
  127. /* Return 1 if REG is clobbered in IN.
  128.    Return 0 if REG is used in IN (other than being clobbered).
  129.    Return 2 if REG does not appear in IN.  */
  130.  
  131. static int
  132. reg_clobbered_p (reg, in)
  133.      rtx reg;
  134.      rtx in;
  135. {
  136.   register char *fmt;
  137.   register int i, result = 0;
  138.  
  139.   register enum rtx_code code;
  140.  
  141.   if (in == 0)
  142.     return 2;
  143.  
  144.   code = GET_CODE (in);
  145.  
  146.   switch (code)
  147.     {
  148.       /* Let these fail out quickly.  */
  149.     case CONST_INT:
  150.     case SYMBOL_REF:
  151.     case CONST:
  152.       return 2;
  153.  
  154.     case SUBREG:
  155.       if (SUBREG_WORD (in) != 0)
  156.     in = gen_rtx (REG, SImode, REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
  157.       else
  158.     in = SUBREG_REG (in);
  159.  
  160.     case REG:
  161.       if (in == reg
  162.       || refers_to_regno_p (REGNO (reg),
  163.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  164.                 in, 0))
  165.     return 0;
  166.       return 2;
  167.  
  168.     case SET:
  169.       if (SET_SRC (in) == reg
  170.       || refers_to_regno_p (REGNO (reg),
  171.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  172.                 SET_SRC (in), 0))
  173.     return 0;
  174.  
  175.       if (SET_DEST (in) == reg)
  176.     return 1;
  177.  
  178.       if (refers_to_regno_p (REGNO (reg),
  179.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  180.                  SET_DEST (in), 0))
  181.     if (GET_CODE (SET_DEST (in)) == REG
  182.         || GET_CODE (SET_DEST (in)) == SUBREG)
  183.       return 1;
  184.     else
  185.       return 0;
  186.       return 2;
  187.  
  188.     case USE:
  189.       if (XEXP (in, 0) == reg
  190.       || refers_to_regno_p (REGNO (reg),
  191.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  192.                 XEXP (in, 0), 0))
  193.     return 0;
  194.       return 2;
  195.  
  196.     case CLOBBER:
  197.       if (XEXP (in, 0) == reg)
  198.     return 1;
  199.       /* If the CLOBBER expression is a SUBREG, accept that as a
  200.      clobber.  But if it is some expression based on this register,
  201.      that is like a USE as far as this register is concerned,
  202.      so we won't take it.  */
  203.       if (refers_to_regno_p (REGNO (reg),
  204.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  205.                  XEXP (in, 0), 0))
  206.     if (GET_CODE (XEXP (in, 0)) == REG
  207.         || GET_CODE (XEXP (in, 0)) == SUBREG)
  208.       return 1;
  209.     else
  210.       return 0;
  211.       return 2;
  212.     }
  213.  
  214.   fmt = GET_RTX_FORMAT (code);
  215.  
  216.   result = 2;
  217.  
  218.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  219.     {
  220.       if (fmt[i] == 'E')
  221.     {
  222.       register int j;
  223.       for (j = XVECLEN (in, i) - 1; j >= 0; j--)
  224.         switch (reg_clobbered_p (reg, XVECEXP (in, i, j)))
  225.           {
  226.           case 0:
  227.         return 0;
  228.           case 2:
  229.         continue;
  230.           case 1:
  231.         result = 1;
  232.         break;
  233.           }
  234.     }
  235.       else if (fmt[i] == 'e')
  236.     switch (reg_clobbered_p (reg, XEXP (in, i)))
  237.       {
  238.       case 0:
  239.         return 0;
  240.       case 2:
  241.         continue;
  242.       case 1:
  243.         result = 1;
  244.         break;
  245.       }
  246.     }
  247.   return result;
  248. }
  249.  
  250. /* Return non-zero if OP can be written to without screwing up
  251.    GCC's model of what's going on.  It is assumed that this operand
  252.    appears in the dest position of a SET insn in a conditional
  253.    branch's delay slot.  AFTER is the label to start looking from.  */
  254. int
  255. operand_clobbered_before_used_after (op, after)
  256.      rtx op;
  257.      rtx after;
  258. {
  259.   extern char call_used_regs[];
  260.  
  261.   /* Just experimenting.  */
  262.   if (GET_CODE (op) == CC0)
  263.     return 1;
  264.   if (GET_CODE (op) == REG)
  265.     {
  266.       rtx insn;
  267.  
  268.       if (op == stack_pointer_rtx)
  269.     return 0;
  270.  
  271.       for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
  272.     {
  273.       if (GET_CODE (insn) == NOTE)
  274.         continue;
  275.       if (GET_CODE (insn) == INSN
  276.           || GET_CODE (insn) == JUMP_INSN
  277.           || GET_CODE (insn) == CALL_INSN)
  278.         {
  279.           switch (reg_clobbered_p (op, PATTERN (insn)))
  280.         {
  281.         case 0:
  282.           return 0;
  283.         case 2:
  284.           break;
  285.         case 1:
  286.           return 1;
  287.         }
  288.           if (dead_or_set_p (insn, op))
  289.         return 1;
  290.         }
  291.       else if (GET_CODE (insn) == CODE_LABEL)
  292.         return 0;
  293.       if (GET_CODE (insn) == JUMP_INSN)
  294.         {
  295.           if (condjump_p (insn))
  296.         return 0;
  297.           /* This is a jump insn which has already
  298.          been mangled.  We can't tell what it does.  */
  299.           if (GET_CODE (PATTERN (insn)) == PARALLEL)
  300.         return 0;
  301.           if (! JUMP_LABEL (insn))
  302.         return 0;
  303.           /* Keep following jumps.  */
  304.           insn = JUMP_LABEL (insn);
  305.         }
  306.     }
  307.       return 1;
  308.     }
  309.  
  310.   /* In both of these cases, the first insn executed
  311.      for this op will be a sethi %hi(whatever),%g1,
  312.      which is tolerable.  */
  313.   if (GET_CODE (op) == MEM)
  314.     return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
  315.  
  316.   return 0;
  317. }
  318.  
  319. /* Return non-zero if this pattern, as a source to a "SET",
  320.    is known to yield an instruction of unit size.  */
  321. int
  322. single_insn_src_p (op, mode)
  323.      rtx op;
  324.      enum machine_mode mode;
  325. {
  326.   switch (GET_CODE (op))
  327.     {
  328.     case CONST_INT:
  329. #if 1
  330.       /* This is not always a single insn src, technically,
  331.      but output_delayed_branch knows how to deal with it.  */
  332.       return 1;
  333. #else
  334.       if (SMALL_INT (op))
  335.     return 1;
  336.       /* We can put this set insn into delay slot, because this is one
  337.      insn; 'sethi'.  */
  338.       if ((INTVAL (op) & 0x3ff) == 0)
  339.     return 1;
  340.  
  341.       /* This is not a single insn src, technically,
  342.      but output_delayed_branch knows how to deal with it.  */
  343.       return 1;
  344. #endif
  345.  
  346. #if 1
  347.     case SYMBOL_REF:
  348.       /* This is not a single insn src, technically,
  349.      but output_delayed_branch knows how to deal with it.  */
  350.       return 1;
  351. #else
  352.       return 0;
  353. #endif
  354.  
  355.     case REG:
  356.       return 1;
  357.  
  358.     case MEM:
  359. #if 0
  360.       /* This is not a single insn src, technically,
  361.      but output_delayed_branch knows how to deal with it.  */
  362.       if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
  363.     return 0;
  364. #endif
  365.       return 1;
  366.  
  367.       /* We never need to negate or complement constants.  */
  368.     case NEG:
  369.       return (mode != DFmode);
  370.     case NOT:
  371.       return 1;
  372.  
  373.     case COMPARE:
  374.     case MINUS:
  375.       /* If the target is cc0, then these insns will take
  376.      two insns (one being a nop).  */
  377.       return (mode != SFmode && mode != DFmode);
  378.     case PLUS:
  379.     case AND:
  380.     case IOR:
  381.     case XOR:
  382.     case LSHIFT:
  383.     case ASHIFT:
  384.     case ASHIFTRT:
  385.     case LSHIFTRT:
  386.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  387.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  388.     return 0;
  389.       return 1;
  390.  
  391.     case SUBREG:
  392.       if (SUBREG_WORD (op) != 0)
  393.     return 0;
  394.       return single_insn_src_p (SUBREG_REG (op), mode);
  395.  
  396.     case SIGN_EXTEND:
  397.     case ZERO_EXTEND:
  398.       /* Lazy... could check for more cases.  */
  399.       if (GET_CODE (XEXP (op, 0)) == MEM
  400.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  401.     return 1;
  402.       return 0;
  403.  
  404.       /* Not doing floating point, since they probably
  405.      take longer than the branch slot they might fill.  */
  406.     case FLOAT_EXTEND:
  407.     case FLOAT_TRUNCATE:
  408.     case FLOAT:
  409.     case FIX:
  410.     case UNSIGNED_FLOAT:
  411.     case UNSIGNED_FIX:
  412.       return 0;
  413.  
  414.     default:
  415.       return 0;
  416.     }
  417. }
  418.  
  419. /* Nonzero only if this *really* is a single insn operand.  */
  420. int
  421. strict_single_insn_op_p (op, mode)
  422.      rtx op;
  423.      enum machine_mode mode;
  424. {
  425.   if (mode == VOIDmode)
  426.     mode = GET_MODE (op);
  427.  
  428.   switch (GET_CODE (op))
  429.     {
  430.     case CC0:
  431.       return 1;
  432.  
  433.     case CONST_INT:
  434.       if (SMALL_INT (op))
  435.     return 1;
  436.       /* We can put this set insn into delay slot, because this is one
  437.      insn; 'sethi'.  */
  438.       if ((INTVAL (op) & 0x3ff) == 0)
  439.     return 1;
  440.       return 0;
  441.  
  442.     case SYMBOL_REF:
  443.       return 0;
  444.  
  445.     case REG:
  446.       return (mode != DFmode && mode != DImode);
  447.  
  448.     case MEM:
  449.       if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
  450.     return (mode != DFmode && mode != DImode);
  451.       return 0;
  452.  
  453.       /* We never need to negate or complement constants.  */
  454.     case NEG:
  455.       return (mode != DFmode);
  456.     case NOT:
  457.       return 1;
  458.  
  459.     case COMPARE:
  460.     case MINUS:
  461.       /* If the target is cc0, then these insns will take
  462.      two insns (one being a nop).  */
  463.       return (mode != SFmode && mode != DFmode);
  464.     case PLUS:
  465.     case AND:
  466.     case IOR:
  467.     case XOR:
  468.     case LSHIFT:
  469.     case ASHIFT:
  470.     case ASHIFTRT:
  471.     case LSHIFTRT:
  472.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  473.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  474.     return 0;
  475.       return 1;
  476.  
  477.     case SUBREG:
  478.       if (SUBREG_WORD (op) != 0)
  479.     return 0;
  480.       return strict_single_insn_op_p (SUBREG_REG (op), mode);
  481.  
  482.     case SIGN_EXTEND:
  483.     case ZERO_EXTEND:
  484.       if (GET_CODE (XEXP (op, 0)) == MEM
  485.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  486.     return 1;
  487.       return 0;
  488.  
  489.       /* Not doing floating point, since they probably
  490.      take longer than the branch slot they might fill.  */
  491.     case FLOAT_EXTEND:
  492.     case FLOAT_TRUNCATE:
  493.     case FLOAT:
  494.     case FIX:
  495.     case UNSIGNED_FLOAT:
  496.     case UNSIGNED_FIX:
  497.       return 0;
  498.  
  499.     default:
  500.       return 0;
  501.     }
  502. }
  503.  
  504. /* Return truth value of whether OP is a relational operator.  */
  505. int
  506. relop (op, mode)
  507.      rtx op;
  508.      enum machine_mode mode;
  509. {
  510.   switch (GET_CODE (op))
  511.     {
  512.     case EQ:
  513.     case NE:
  514.     case GT:
  515.     case GE:
  516.     case LT:
  517.     case LE:
  518.     case GTU:
  519.     case GEU:
  520.     case LTU:
  521.     case LEU:
  522.       return 1;
  523.     }
  524.   return 0;
  525. }
  526.  
  527. /* Return truth value of wheterh OP is EQ or NE.  */
  528. int
  529. eq_or_neq (op, mode)
  530.      rtx op;
  531.      enum machine_mode mode;
  532. {
  533.   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
  534. }
  535.  
  536. /* Return truth value of whether OP can be used as an operands in a three
  537.    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
  538.  
  539. int
  540. arith_operand (op, mode)
  541.      rtx op;
  542.      enum machine_mode mode;
  543. {
  544.   return (register_operand (op, mode)
  545.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  546. }
  547.  
  548. /* Return truth value of whether OP can be used as an operand in a two
  549.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  550.  
  551. int
  552. arith32_operand (op, mode)
  553.      rtx op;
  554.      enum machine_mode mode;
  555. {
  556.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  557. }
  558.  
  559. /* Return truth value of whether OP is a integer which fits the
  560.    range constraining immediate operands in three-address insns.  */
  561.  
  562. int
  563. small_int (op, mode)
  564.      rtx op;
  565.      enum machine_mode mode;
  566. {
  567.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  568. }
  569.  
  570. /* Return the best assembler insn template
  571.    for moving operands[1] into operands[0] as a fullword.  */
  572.  
  573. static char *
  574. singlemove_string (operands)
  575.      rtx *operands;
  576. {
  577.   if (GET_CODE (operands[0]) == MEM)
  578.     {
  579.       if (GET_CODE (operands[1]) != MEM)
  580.     if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  581.       {
  582.         if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  583.            && cc_prev_status.mdep == XEXP (operands[0], 0)))
  584.           output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  585.         cc_status.flags |= CC_KNOW_HI_G1;
  586.         cc_status.mdep = XEXP (operands[0], 0);
  587.         return "st %1,[%%lo(%m0)+%%g1]";
  588.       }
  589.     else
  590.       return "st %r1,%0";
  591.       else
  592.     {
  593.       rtx xoperands[2];
  594.  
  595.       cc_status.flags &= ~CC_F0_IS_0;
  596.       xoperands[0] = gen_rtx (REG, SFmode, 32);
  597.       xoperands[1] = operands[1];
  598.       output_asm_insn (singlemove_string (xoperands), xoperands);
  599.       xoperands[1] = xoperands[0];
  600.       xoperands[0] = operands[0];
  601.       output_asm_insn (singlemove_string (xoperands), xoperands);
  602.       return "";
  603.     }
  604.     }
  605.   if (GET_CODE (operands[1]) == MEM)
  606.     {
  607.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  608.     {
  609.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  610.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  611.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  612.       cc_status.flags |= CC_KNOW_HI_G1;
  613.       cc_status.mdep = XEXP (operands[1], 0);
  614.       return "ld [%%lo(%m1)+%%g1],%0";
  615.     }
  616.       return "ld %1,%0";
  617.     }
  618.   return "mov %1,%0";
  619. }
  620.  
  621. /* Output assembler code to perform a doubleword move insn
  622.    with operands OPERANDS.  */
  623.  
  624. char *
  625. output_move_double (operands)
  626.      rtx *operands;
  627. {
  628.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  629.   rtx latehalf[2];
  630.   rtx addreg0 = 0, addreg1 = 0;
  631.  
  632.   /* First classify both operands.  */
  633.  
  634.   if (REG_P (operands[0]))
  635.     optype0 = REGOP;
  636.   else if (offsettable_memref_p (operands[0]))
  637.     optype0 = OFFSOP;
  638.   else if (GET_CODE (operands[0]) == MEM)
  639.     optype0 = MEMOP;
  640.   else
  641.     optype0 = RNDOP;
  642.  
  643.   if (REG_P (operands[1]))
  644.     optype1 = REGOP;
  645.   else if (CONSTANT_P (operands[1])
  646.        || GET_CODE (operands[1]) == CONST_DOUBLE)
  647.     optype1 = CNSTOP;
  648.   else if (offsettable_memref_p (operands[1]))
  649.     optype1 = OFFSOP;
  650.   else if (GET_CODE (operands[1]) == MEM)
  651.     optype1 = MEMOP;
  652.   else
  653.     optype1 = RNDOP;
  654.  
  655.   /* Check for the cases that the operand constraints are not
  656.      supposed to allow to happen.  Abort if we get one,
  657.      because generating code for these cases is painful.  */
  658.  
  659.   if (optype0 == RNDOP || optype1 == RNDOP)
  660.     abort ();
  661.  
  662.   /* If an operand is an unoffsettable memory ref, find a register
  663.      we can increment temporarily to make it refer to the second word.  */
  664.  
  665.   if (optype0 == MEMOP)
  666.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  667.  
  668.   if (optype1 == MEMOP)
  669.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  670.  
  671.   /* Ok, we can do one word at a time.
  672.      Normally we do the low-numbered word first,
  673.      but if either operand is autodecrementing then we
  674.      do the high-numbered word first.
  675.  
  676.      In either case, set up in LATEHALF the operands to use
  677.      for the high-numbered word and in some cases alter the
  678.      operands in OPERANDS to be suitable for the low-numbered word.  */
  679.  
  680.   if (optype0 == REGOP)
  681.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  682.   else if (optype0 == OFFSOP)
  683.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  684.   else
  685.     latehalf[0] = operands[0];
  686.  
  687.   if (optype1 == REGOP)
  688.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  689.   else if (optype1 == OFFSOP)
  690.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  691.   else if (optype1 == CNSTOP)
  692.     {
  693.       if (CONSTANT_P (operands[1]))
  694.     latehalf[1] = const0_rtx;
  695.       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  696.     {
  697.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  698.                  CONST_DOUBLE_HIGH (operands[1]));
  699.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  700.                  CONST_DOUBLE_LOW (operands[1]));
  701.     }
  702.     }
  703.   else
  704.     latehalf[1] = operands[1];
  705.  
  706.   /* If the first move would clobber the source of the second one,
  707.      do them in the other order.
  708.  
  709.      RMS says "This happens only for registers;
  710.      such overlap can't happen in memory unless the user explicitly
  711.      sets it up, and that is an undefined circumstance."
  712.  
  713.      but it happens on the sparc when loading parameter registers,
  714.      so I am going to define that circumstance, and make it work
  715.      as expected.  */
  716.  
  717.   /* Easy case: try moving both words at once.  */
  718.   /* First check for moving between an even/odd register pair
  719.      and a memory location.  */
  720.   if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
  721.        && (REGNO (operands[0]) & 1) == 0)
  722.       || (optype0 != REGOP && optype1 != CNSTOP && optype1 == REGOP
  723.       && (REGNO (operands[1]) & 1) == 0))
  724.     {
  725.       rtx op1, op2;
  726.       rtx base = 0, offset = const0_rtx;
  727.  
  728.       /* OP1 gets the register pair, and OP2 gets the memory address.  */
  729.       if (optype0 == REGOP)
  730.     op1 = operands[0], op2 = XEXP (operands[1], 0);
  731.       else
  732.     op1 = operands[1], op2 = XEXP (operands[0], 0);
  733.  
  734.       /* Now see if we can trust the address to be 8-byte aligned.  */
  735.       /* Trust global variables.  */
  736.       if (CONSTANT_ADDRESS_P (op2))
  737.     {
  738.       operands[0] = op1;
  739.       operands[1] = op2;
  740.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  741.          && cc_prev_status.mdep == op2))
  742.         output_asm_insn ("sethi %%hi(%1),%%g1", operands);
  743.       cc_status.flags |= CC_KNOW_HI_G1;
  744.       cc_status.mdep = op2;
  745.       if (op1 == operands[0])
  746.         return "ldd [%%lo(%1)+%%g1],%0";
  747.       else
  748.         return "std [%%lo(%1)+%%g1],%0";
  749.     }
  750.  
  751.       if (GET_CODE (op2) == PLUS)
  752.     {
  753.       if (GET_CODE (XEXP (op2, 0)) == REG)
  754.         base = XEXP (op2, 0), offset = XEXP (op2, 1);
  755.       else if (GET_CODE (XEXP (op2, 1)) == REG)
  756.         base = XEXP (op2, 1), offset = XEXP (op2, 0);
  757.     }
  758.  
  759.       /* Trust round enough offsets from the stack or frame pointer.  */
  760.       if (base
  761.       && (REGNO (base) == FRAME_POINTER_REGNUM
  762.           || REGNO (base) == STACK_POINTER_REGNUM))
  763.     {
  764.       if (GET_CODE (offset) == CONST_INT
  765.           && (INTVAL (offset) & 0x7) == 0)
  766.         {
  767.           if (op1 == operands[0])
  768.         return "ldd %1,%0";
  769.           else
  770.         return "std %1,%0";
  771.         }
  772.     }
  773.       else
  774.     {
  775.       /* We know structs not on the stack are properly aligned.
  776.          Since a double asks for 8-byte alignment,
  777.          we know it must have got that if it is in a struct.
  778.          But a DImode need not be 8-byte aligned, because it could be a
  779.          struct containing two ints or pointers.  */
  780.  
  781.       /* Sun fucks us here.  We cannot trust references
  782.          to doubles via varying addresses.  It might be on the stack
  783.          even if we don't know that it is; and then it might not be
  784.          double-word aligned.  */
  785. #if 0
  786.       if (GET_CODE (operands[1]) == MEM && GET_MODE (operands[1]) == DFmode
  787.           && MEM_IN_STRUCT_P (operands[1]))
  788.         return "ldd %1,%0";
  789.       else if (GET_CODE (operands[0]) == MEM
  790.            && GET_MODE (operands[0]) == DFmode
  791.            && MEM_IN_STRUCT_P (operands[0]))
  792.         return "std %1,%0";
  793. #endif
  794.     }
  795.     }
  796.  
  797.   if (optype0 == REGOP && optype1 == REGOP
  798.       && REGNO (operands[0]) == REGNO (latehalf[1]))
  799.     {
  800.       /* Make any unoffsettable addresses point at high-numbered word.  */
  801.       if (addreg0)
  802.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  803.       if (addreg1)
  804.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  805.  
  806.       /* Do that word.  */
  807.       output_asm_insn (singlemove_string (latehalf), latehalf);
  808.  
  809.       /* Undo the adds we just did.  */
  810.       if (addreg0)
  811.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  812.       if (addreg1)
  813.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  814.  
  815.       /* Do low-numbered word.  */
  816.       return singlemove_string (operands);
  817.     }
  818.   else if (optype0 == REGOP && optype1 != REGOP
  819.        && reg_overlap_mentioned_p (operands[0], operands[1]))
  820.     {
  821.       /* Do the late half first.  */
  822.       output_asm_insn (singlemove_string (latehalf), latehalf);
  823.       /* Then clobber.  */
  824.       return singlemove_string (operands);
  825.     }
  826.  
  827.   /* Normal case: do the two words, low-numbered first.  */
  828.  
  829.   output_asm_insn (singlemove_string (operands), operands);
  830.  
  831.   /* Make any unoffsettable addresses point at high-numbered word.  */
  832.   if (addreg0)
  833.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  834.   if (addreg1)
  835.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  836.  
  837.   /* Do that word.  */
  838.   output_asm_insn (singlemove_string (latehalf), latehalf);
  839.  
  840.   /* Undo the adds we just did.  */
  841.   if (addreg0)
  842.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  843.   if (addreg1)
  844.     output_asm_insn ("add %0,-0x4,%0", &addreg1);
  845.  
  846.   return "";
  847. }
  848.  
  849. static char *
  850. output_fp_move_double (operands)
  851.      rtx *operands;
  852. {
  853.   if (FP_REG_P (operands[0]))
  854.     {
  855.       if (FP_REG_P (operands[1]))
  856.     {
  857.       output_asm_insn ("fmovs %1,%0", operands);
  858.       operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
  859.       operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
  860.       return "fmovs %1,%0";
  861.     }
  862.       if (GET_CODE (operands[1]) == REG)
  863.     {
  864.       if ((REGNO (operands[1]) & 1) == 0)
  865.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  866.       else
  867.         {
  868.           rtx xoperands[3];
  869.           xoperands[0] = operands[0];
  870.           xoperands[1] = operands[1];
  871.           xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  872.           output_asm_insn ("st %2,[%%fp-4]\n\tst %1,[%%fp-8]\n\tldd [%%fp-8],%0", xoperands);
  873.           return "";
  874.         }
  875.     }
  876.       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
  877.       && (((XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
  878.           || XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
  879.       && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
  880.       && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) == 0)
  881.           || (REG_P (XEXP (XEXP (operands[1], 0), 0))
  882.           && REG_P (XEXP (XEXP (operands[1], 0), 1)))))
  883.         {
  884.           return "ldd %1,%0";
  885.         }
  886.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  887.     {
  888.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  889.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  890.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  891.       cc_status.flags |= CC_KNOW_HI_G1;
  892.       cc_status.mdep = XEXP (operands[1], 0);
  893.       return "ldd [%%lo(%m1)+%%g1],%0";
  894.     }
  895.     {
  896.       rtx xoperands[2];
  897.       output_asm_insn ("ld %1,%0", operands);
  898.       xoperands[0] = gen_rtx (REG, GET_MODE (operands[0]),
  899.                   REGNO (operands[0]) + 1);
  900.       xoperands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
  901.                   plus_constant (XEXP (operands[1], 0), 4));
  902.       output_asm_insn ("ld %1,%0", xoperands);
  903.       return "";
  904.     }
  905.     }
  906.   else if (FP_REG_P (operands[1]))
  907.     {
  908.       if (GET_CODE (operands[0]) == REG)
  909.     {
  910.       if ((REGNO (operands[0]) & 1) == 0)
  911.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  912.       else
  913.         {
  914.           rtx xoperands[3];
  915.           xoperands[2] = operands[1];
  916.           xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  917.           xoperands[0] = operands[0];
  918.           output_asm_insn ("std %2,[%%fp-8]\n\tld [%%fp-4],%1\n\tld [%%fp-8],%0", xoperands);
  919.           return "";
  920.         }
  921.     }
  922.       /* Use std if we can be sure it is well-aligned.  */
  923.       if (GET_CODE (XEXP (operands[0], 0)) == PLUS
  924.       && (((XEXP (XEXP (operands[0], 0), 0) == frame_pointer_rtx
  925.         || XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
  926.            && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
  927.            && (INTVAL (XEXP (XEXP (operands[0], 0), 1)) & 0x7) == 0)
  928.           /* Arrays are known to be aligned,
  929.          and reg+reg addresses are used (on this machine)
  930.          only for array accesses.  */
  931.           || (REG_P (XEXP (XEXP (operands[0], 0), 0))
  932.           && REG_P (XEXP (XEXP (operands[0], 0), 1)))))
  933.     return "std %1,%0";
  934.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  935.     {
  936.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  937.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  938.         output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  939.       cc_status.flags |= CC_KNOW_HI_G1;
  940.       cc_status.mdep = XEXP (operands[0], 0);
  941.       return "std %1,[%%lo(%m0)+%%g1]";
  942.     }
  943.       /* Otherwise use two st insns.  */
  944.       {
  945.     rtx xoperands[2];
  946.     output_asm_insn ("st %r1,%0", operands);
  947.     xoperands[1] = gen_rtx (REG, GET_MODE (operands[1]),
  948.                 REGNO (operands[1]) + 1);
  949.     xoperands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
  950.                 plus_constant (XEXP (operands[0], 0), 4));
  951.     output_asm_insn ("st %r1,%0", xoperands);
  952.     return "";
  953.       }
  954.     }
  955.   else abort ();
  956. }
  957.  
  958. /* Return a REG that occurs in ADDR with coefficient 1.
  959.    ADDR can be effectively incremented by incrementing REG.  */
  960.  
  961. static rtx
  962. find_addr_reg (addr)
  963.      rtx addr;
  964. {
  965.   while (GET_CODE (addr) == PLUS)
  966.     {
  967.       if (GET_CODE (XEXP (addr, 0)) == REG)
  968.     addr = XEXP (addr, 0);
  969.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  970.     addr = XEXP (addr, 1);
  971.       else if (CONSTANT_P (XEXP (addr, 0)))
  972.     addr = XEXP (addr, 1);
  973.       else if (CONSTANT_P (XEXP (addr, 1)))
  974.     addr = XEXP (addr, 0);
  975.       else
  976.     abort ();
  977.     }
  978.   if (GET_CODE (addr) == REG)
  979.     return addr;
  980.   abort ();
  981. }
  982.  
  983. void
  984. output_sized_memop (opname, mode)
  985.      char *opname;
  986.      enum machine_mode mode;
  987. {
  988.   extern struct _iobuf *asm_out_file;
  989.  
  990.   static char *ld_size_suffix[] = { "ub", "uh", "", "?", "d" };
  991.   static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
  992.   char *modename
  993.     = (opname[0] == 'l' ? ld_size_suffix : st_size_suffix)[GET_MODE_SIZE (mode) >> 1];
  994.  
  995.   fprintf (asm_out_file, "\t%s%s", opname, modename);
  996. }
  997.  
  998. /* Output a store-in-memory whose operands are OPERANDS[0,1].
  999.    OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.  */
  1000.  
  1001. char *
  1002. output_store (operands)
  1003.      rtx *operands;
  1004. {
  1005.   enum machine_mode mode = GET_MODE (operands[0]);
  1006.   rtx address = XEXP (operands[0], 0);
  1007.  
  1008.   cc_status.flags |= CC_KNOW_HI_G1;
  1009.   cc_status.mdep = address;
  1010.  
  1011.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1012.      && address == cc_prev_status.mdep))
  1013.     {
  1014.       output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  1015.       cc_prev_status.mdep = address;
  1016.     }
  1017.  
  1018.   /* Store zero in two parts when appropriate.  */
  1019.   if (mode == DFmode && operands[1] == dconst0_rtx)
  1020.     {
  1021.       /* We can't cross a page boundary here because the
  1022.      SYMBOL_REF must be double word aligned, and for this
  1023.      to be the case, SYMBOL_REF+4 cannot cross.  */
  1024.       output_sized_memop ("st", SImode);
  1025.       output_asm_insn ("%r1,[%%g1+%%lo(%m0)]", operands);
  1026.       output_sized_memop ("st", SImode);
  1027.       return "%r1,[%%g1+%%lo(%m0)+4]";
  1028.     }
  1029.  
  1030.   /* Code below isn't smart enough to move a doubleword in two parts,
  1031.      so use output_move_double to do that in the cases that require it.  */
  1032.   if ((mode == DImode || mode == DFmode)
  1033.       && (GET_CODE (operands[1]) == REG
  1034.       && (REGNO (operands[1]) & 1)))
  1035.     return output_move_double (operands);
  1036.  
  1037.   output_sized_memop ("st", mode);
  1038.   return "%r1,[%%g1+%%lo(%m0)]";
  1039. }
  1040.  
  1041. /* Output a fixed-point load-from-memory whose operands are OPERANDS[0,1].
  1042.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.  */
  1043.  
  1044. char *
  1045. output_load_fixed (operands)
  1046.      rtx *operands;
  1047. {
  1048.   enum machine_mode mode = GET_MODE (operands[0]);
  1049.   rtx address = XEXP (operands[1], 0);
  1050.  
  1051.   /* We don't bother trying to see if we know %hi(address).
  1052.      This is because we are doing a load, and if we know the
  1053.      %hi value, we probably also know that value in memory.  */
  1054.   cc_status.flags |= CC_KNOW_HI_G1;
  1055.   cc_status.mdep = address;
  1056.  
  1057.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1058.      && address == cc_prev_status.mdep
  1059.      && cc_prev_status.mdep == cc_status.mdep))
  1060.     {
  1061.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1062.       cc_prev_status.mdep = address;
  1063.     }
  1064.  
  1065.   /* Code below isn't smart enough to do a doubleword in two parts.
  1066.      So handle that case the slow way.  */
  1067.   if (mode == DImode
  1068.       && GET_CODE (operands[0]) == REG   /* Moving to nonaligned reg pair */
  1069.       && (REGNO (operands[0]) & 1))
  1070.     return output_move_double (operands);
  1071.  
  1072.   output_sized_memop ("ld", mode);
  1073.   if (GET_CODE (operands[0]) == REG)
  1074.     return "[%%g1+%%lo(%m1)],%0";
  1075.   abort ();
  1076. }
  1077.  
  1078. /* Output a floating-point load-from-memory whose operands are OPERANDS[0,1].
  1079.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
  1080.    We also handle the case where OPERANDS[0] is a mem.  */
  1081.  
  1082. char *
  1083. output_load_floating (operands)
  1084.      rtx *operands;
  1085. {
  1086.   enum machine_mode mode = GET_MODE (operands[0]);
  1087.   rtx address = XEXP (operands[1], 0);
  1088.  
  1089.   /* We don't bother trying to see if we know %hi(address).
  1090.      This is because we are doing a load, and if we know the
  1091.      %hi value, we probably also know that value in memory.  */
  1092.   cc_status.flags |= CC_KNOW_HI_G1;
  1093.   cc_status.mdep = address;
  1094.  
  1095.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1096.      && address == cc_prev_status.mdep
  1097.      && cc_prev_status.mdep == cc_status.mdep))
  1098.     {
  1099.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1100.       cc_prev_status.mdep = address;
  1101.     }
  1102.  
  1103.   if (mode == DFmode)
  1104.     {
  1105.       if (REG_P (operands[0]))
  1106.     {
  1107.       if (REGNO (operands[0]) & 1)
  1108.         return output_move_double (operands);
  1109.       else
  1110.         return "ldd [%%g1+%%lo(%m1)],%0";
  1111.     }
  1112.       cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0);
  1113.       output_asm_insn ("ldd [%%g1+%%lo(%m1)],%%f0", operands);
  1114.       operands[1] = gen_rtx (REG, DFmode, 32);
  1115.       return output_fp_move_double (operands);
  1116.     }
  1117.  
  1118.   if (GET_CODE (operands[0]) == MEM)
  1119.     {
  1120.       cc_status.flags &= ~CC_F1_IS_0;
  1121.       output_asm_insn ("ld [%%g1+%%lo(%1)],%%f1", operands);
  1122.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  1123.     {
  1124.       cc_status.mdep = XEXP (operands[0], 0);
  1125.       return "sethi %%hi(%m0),%%g1\n\tst %%f1,[%%g1+%%lo(%m0)]";
  1126.     }
  1127.       else
  1128.     return "st %%f1,%0";
  1129.     }
  1130.   return "ld [%%g1+%%lo(%m1)],%0";
  1131. }
  1132.  
  1133. /* Load the address specified by OPERANDS[3] into the register
  1134.    specified by OPERANDS[0].
  1135.  
  1136.    OPERANDS[3] may be the result of a sum, hence it could either be:
  1137.  
  1138.    (1) CONST
  1139.    (2) REG
  1140.    (2) REG + CONST_INT
  1141.    (3) REG + REG + CONST_INT
  1142.    (4) REG + REG  (special case of 3).
  1143.  
  1144.    Note that (3) is not a legitimate address.
  1145.    All cases are handled here.  */
  1146.  
  1147. void
  1148. output_load_address (operands)
  1149.      rtx *operands;
  1150. {
  1151.   rtx base, offset;
  1152.  
  1153.   if (CONSTANT_P (operands[3]))
  1154.     {
  1155.       output_asm_insn ("set %3,%0", operands);
  1156.       return;
  1157.     }
  1158.  
  1159.   if (REG_P (operands[3]))
  1160.     {
  1161.       if (REGNO (operands[0]) != REGNO (operands[3]))
  1162.     output_asm_insn ("mov %3,%0", operands);
  1163.       return;
  1164.     }
  1165.  
  1166.   if (GET_CODE (operands[3]) != PLUS)
  1167.     abort ();
  1168.  
  1169.   base = XEXP (operands[3], 0);
  1170.   offset = XEXP (operands[3], 1);
  1171.  
  1172.   if (GET_CODE (base) == CONST_INT)
  1173.     {
  1174.       rtx tmp = base;
  1175.       base = offset;
  1176.       offset = tmp;
  1177.     }
  1178.  
  1179.   if (GET_CODE (offset) != CONST_INT)
  1180.     {
  1181.       /* Operand is (PLUS (REG) (REG)).  */
  1182.       base = operands[3];
  1183.       offset = const0_rtx;
  1184.     }
  1185.  
  1186.   if (REG_P (base))
  1187.     {
  1188.       operands[6] = base;
  1189.       operands[7] = offset;
  1190.       if (SMALL_INT (offset))
  1191.     output_asm_insn ("add %6,%7,%0", operands);
  1192.       else
  1193.     output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
  1194.     }
  1195.   else if (GET_CODE (base) == PLUS)
  1196.     {
  1197.       operands[6] = XEXP (base, 0);
  1198.       operands[7] = XEXP (base, 1);
  1199.       operands[8] = offset;
  1200.  
  1201.       if (SMALL_INT (offset))
  1202.     output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
  1203.       else
  1204.     output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
  1205.     }
  1206.   else
  1207.     abort ();
  1208. }
  1209.  
  1210. /* Output code to place a size count SIZE in register REG.
  1211.    ALIGN is the size of the unit of transfer.
  1212.  
  1213.    Because block moves are pipelined, we don't include the
  1214.    first element in the transfer of SIZE to REG.  */
  1215.  
  1216. static void
  1217. output_size_for_block_move (size, reg, align)
  1218.      rtx size, reg;
  1219.      rtx align;
  1220. {
  1221.   rtx xoperands[3];
  1222.  
  1223.   xoperands[0] = reg;
  1224.   xoperands[1] = size;
  1225.   xoperands[2] = align;
  1226.   if (GET_CODE (size) == REG)
  1227.     output_asm_insn ("sub %1,%2,%0", xoperands);
  1228.   else
  1229.     {
  1230.       xoperands[1]
  1231.     = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
  1232.       cc_status.flags &= ~ CC_KNOW_HI_G1;
  1233.       output_asm_insn ("set %1,%0", xoperands);
  1234.     }
  1235. }
  1236.  
  1237. /* Emit code to perform a block move.
  1238.  
  1239.    OPERANDS[0] is the destination.
  1240.    OPERANDS[1] is the source.
  1241.    OPERANDS[2] is the size.
  1242.    OPERANDS[3] is the alignment safe to use.
  1243.    OPERANDS[4] is a register we can safely clobber as a temp.  */
  1244.  
  1245. char *
  1246. output_block_move (operands)
  1247.      rtx *operands;
  1248. {
  1249.   /* A vector for our computed operands.  Note that load_output_address
  1250.      makes use of (and can clobber) up to the 8th element of this vector.  */
  1251.   rtx xoperands[10];
  1252.   rtx zoperands[10];
  1253.   static int movstrsi_label = 0;
  1254.   int i, j;
  1255.   rtx temp1 = operands[4];
  1256.   rtx alignrtx = operands[3];
  1257.   int align = INTVAL (alignrtx);
  1258.  
  1259.   xoperands[0] = operands[0];
  1260.   xoperands[1] = operands[1];
  1261.   xoperands[2] = temp1;
  1262.  
  1263.   /* We can't move more than four bytes at a time
  1264.      because we have only one register to move them through.  */
  1265.   if (align > 4)
  1266.     {
  1267.       align = 4;
  1268.       alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
  1269.     }
  1270.  
  1271.   /* Since we clobber untold things, nix the condition codes.  */
  1272.   CC_STATUS_INIT;
  1273.  
  1274.   /* Recognize special cases of block moves.  These occur
  1275.      when GNU C++ is forced to treat something as BLKmode
  1276.      to keep it in memory, when its mode could be represented
  1277.      with something smaller.
  1278.  
  1279.      We cannot do this for global variables, since we don't know
  1280.      what pages they don't cross.  Sigh.  */
  1281.   if (GET_CODE (operands[2]) == CONST_INT
  1282.       && INTVAL (operands[2]) <= 16
  1283.       && ! CONSTANT_ADDRESS_P (operands[0])
  1284.       && ! CONSTANT_ADDRESS_P (operands[1]))
  1285.     {
  1286.       int size = INTVAL (operands[2]);
  1287.  
  1288.       cc_status.flags &= ~CC_KNOW_HI_G1;
  1289.       if (align == 1)
  1290.     {
  1291.       if (memory_address_p (QImode, plus_constant (xoperands[0], size))
  1292.           && memory_address_p (QImode, plus_constant (xoperands[1], size)))
  1293.         {
  1294.           /* We will store different integers into this particular RTX.  */
  1295.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1296.           for (i = size-1; i >= 0; i--)
  1297.         {
  1298.           INTVAL (xoperands[2]) = i;
  1299.           output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
  1300.                    xoperands);
  1301.         }
  1302.           return "";
  1303.         }
  1304.     }
  1305.       else if (align == 2)
  1306.     {
  1307.       if (memory_address_p (HImode, plus_constant (xoperands[0], size))
  1308.           && memory_address_p (HImode, plus_constant (xoperands[1], size)))
  1309.         {
  1310.           /* We will store different integers into this particular RTX.  */
  1311.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1312.           for (i = (size>>1)-1; i >= 0; i--)
  1313.         {
  1314.           INTVAL (xoperands[2]) = i<<1;
  1315.           output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
  1316.                    xoperands);
  1317.         }
  1318.           return "";
  1319.         }
  1320.     }
  1321.       else
  1322.     {
  1323.       if (memory_address_p (SImode, plus_constant (xoperands[0], size))
  1324.           && memory_address_p (SImode, plus_constant (xoperands[1], size)))
  1325.         {
  1326.           /* We will store different integers into this particular RTX.  */
  1327.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1328.           for (i = (size>>2)-1; i >= 0; i--)
  1329.         {
  1330.           INTVAL (xoperands[2]) = i<<2;
  1331.           output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
  1332.                    xoperands);
  1333.         }
  1334.           return "";
  1335.         }
  1336.     }
  1337.     }
  1338.  
  1339.   /* This is the size of the transfer.
  1340.      Either use the register which already contains the size,
  1341.      or use a free register (used by no operands).
  1342.      Also emit code to decrement the size value by ALIGN.  */
  1343.   output_size_for_block_move (operands[2], temp1, alignrtx);
  1344.      
  1345.   zoperands[0] = operands[0];
  1346.   zoperands[3] = plus_constant (operands[0], align);
  1347.   output_load_address (zoperands);
  1348.  
  1349.   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1350.   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
  1351.  
  1352.   if (align == 1)
  1353.     output_asm_insn ("\nLm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
  1354.   else if (align == 2)
  1355.     output_asm_insn ("\nLm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
  1356.   else
  1357.     output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]", xoperands);
  1358.   return "";
  1359. }
  1360.  
  1361. /* What the sparc lacks in hardware, make up for in software.
  1362.    Compute a fairly good sequence of shift and add insns
  1363.    to make a multiply happen.  */
  1364.  
  1365. #define ABS(x) ((x) < 0 ? -(x) : x)
  1366.  
  1367. char *
  1368. output_mul_by_constant (insn, operands, unsignedp)
  1369.      rtx insn;
  1370.      rtx *operands;
  1371.      int unsignedp;
  1372. {
  1373.   int c;            /* Size of constant */
  1374.   int shifts[BITS_PER_WORD];    /* Table of shifts */
  1375.   unsigned int p, log;        /* A power of two, and its log */
  1376.   int d1, d2;            /* Differences of c and p */
  1377.   int first = 1;        /* True if dst has unknown data in it */
  1378.   int i;
  1379.  
  1380.   CC_STATUS_INIT;
  1381.  
  1382.   c = INTVAL (operands[2]);
  1383.   if (c == 0)
  1384.     {
  1385.       /* should not happen.  */
  1386.       abort ();
  1387.       if (GET_CODE (operands[0]) == MEM)
  1388.     return "st %%g0,%0";
  1389.       return "mov %%g0,%0";
  1390.     }
  1391.  
  1392.   output_asm_insn ("! start open coded multiply");
  1393.  
  1394.   /* Clear out the table of shifts. */
  1395.   for (i = 0; i < BITS_PER_WORD; ++i)
  1396.     shifts[i] = 0;
  1397.  
  1398.   while (c)
  1399.     {
  1400.       /* Find the power of two nearest ABS(c) */
  1401.       p = 1, log = 0;
  1402.       do
  1403.     {
  1404.       d1 = ABS(c) - p;
  1405.       p *= 2;
  1406.       ++log;
  1407.     }
  1408.       while (p < ABS(c));
  1409.       d2 = p - ABS(c);
  1410.  
  1411.       /* Make an appropriate entry in shifts for p. */
  1412.       if (d2 < d1)
  1413.     {
  1414.       shifts[log] = c < 0 ? -1 : 1;
  1415.       c = c < 0 ? d2 : -d2;
  1416.     }
  1417.       else
  1418.     {
  1419.       shifts[log - 1] = c < 0 ? -1 : 1;
  1420.       c = c < 0 ? -d1 : d1;
  1421.     }
  1422.     }
  1423.  
  1424.   /* Take care of the first insn in sequence.
  1425.      We know we have at least one. */
  1426.  
  1427.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1428.      of 1 says to add that power of two. */
  1429.   for (i = 0; ; i++)
  1430.     if (shifts[i])
  1431.       {
  1432.     if (i)
  1433.       {
  1434.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
  1435.         output_asm_insn ("sll %1,%2,%%g1", operands);
  1436.       }
  1437.     else output_asm_insn ("mov %1,%%g1", operands);
  1438.  
  1439.     log = i;
  1440.     if (shifts[i] < 0)
  1441.       output_asm_insn ("sub %%g0,%%g1,%0", operands);
  1442.     else
  1443.       output_asm_insn ("mov %%g1,%0", operands);
  1444.     break;
  1445.       }
  1446.  
  1447.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1448.      of 1 says to add that power of two--continued.  */
  1449.   for (i += 1; i < BITS_PER_WORD; ++i)
  1450.     if (shifts[i])
  1451.       {
  1452.     if (i - log > 0)
  1453.       {
  1454.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
  1455.         output_asm_insn ("sll %%g1,%2,%%g1", operands);
  1456.       }
  1457.     else
  1458.       {
  1459.         operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
  1460.         output_asm_insn ("sra %%g1,%2,%%g1", operands);
  1461.       }
  1462.     log = i;
  1463.     if (shifts[i] < 0)
  1464.       output_asm_insn ("sub %0,%%g1,%0", operands);
  1465.     else
  1466.       output_asm_insn ("add %0,%%g1,%0", operands);
  1467.       }
  1468.  
  1469.   output_asm_insn ("! end open coded multiply");
  1470.  
  1471.   return "";
  1472. }
  1473.  
  1474. char *
  1475. output_mul_insn (operands, unsignedp)
  1476.      rtx *operands;
  1477.      int unsignedp;
  1478. {
  1479.   int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
  1480.   int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
  1481.  
  1482.   CC_STATUS_INIT;
  1483.  
  1484.   if (lucky1)
  1485.     {
  1486.       if (lucky2)
  1487.     {
  1488.       if (REGNO (operands[1]) == REGNO (operands[2]))
  1489.         {
  1490.           if (REGNO (operands[1]) == 8)
  1491.         output_asm_insn ("mov %%o0,%%o1");
  1492.           else
  1493.         output_asm_insn ("mov %%o1,%%o0");
  1494.         }
  1495.       output_asm_insn ("call .mul,2\n\tnop", operands);
  1496.     }
  1497.       else
  1498.     {
  1499.       rtx xoperands[2];
  1500.       xoperands[0] = gen_rtx (REG, SImode,
  1501.                   8 ^ (REGNO (operands[1]) == 8));
  1502.       xoperands[1] = operands[2];
  1503.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1504.     }
  1505.     }
  1506.   else if (lucky2)
  1507.     {
  1508.       rtx xoperands[2];
  1509.       xoperands[0] = gen_rtx (REG, SImode,
  1510.                   8 ^ (REGNO (operands[2]) == 8));
  1511.       xoperands[1] = operands[1];
  1512.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1513.     }
  1514.   else
  1515.     {
  1516.       output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
  1517.                operands);
  1518.     }
  1519.  
  1520.   if (REGNO (operands[0]) == 8)
  1521.     return "";
  1522.   return "mov %%o0,%0";
  1523. }
  1524.  
  1525. /* Make floating point register f0 contain 0.
  1526.    SIZE is the number of registers (including f0)
  1527.    which should contain 0.  */
  1528.  
  1529. void
  1530. make_f0_contain_0 (size)
  1531.      int size;
  1532. {
  1533.   if (size == 1)
  1534.     {
  1535.       if ((cc_status.flags & (CC_F0_IS_0)) == 0)
  1536.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1537.       cc_status.flags |= CC_F0_IS_0;
  1538.     }
  1539.   else if (size == 2)
  1540.     {
  1541.       if ((cc_status.flags & CC_F0_IS_0) == 0)
  1542.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1543.       if ((cc_status.flags & (CC_F1_IS_0)) == 0)
  1544.     output_asm_insn ("ld [%%fp-12],%%f1", 0);
  1545.       cc_status.flags |= CC_F0_IS_0 | CC_F1_IS_0;
  1546.     }
  1547. }
  1548.  
  1549. /* Since condition codes don't have logical links, we need to keep
  1550.    their setting and use together for set-cc insns.  */
  1551. void
  1552. gen_scc_insn (code, mode, operands)
  1553.      enum rtx_code code;
  1554.      enum machine_mode mode;
  1555.      rtx *operands;
  1556. {
  1557.   extern rtx sequence_stack;
  1558.   rtx last_insn = XEXP (XEXP (sequence_stack, 1), 0);
  1559.   rtx last_pat;
  1560.  
  1561.   /* Skip back over the CLOBBERs that may precede this insn.  */
  1562.   while (last_insn && GET_CODE (last_insn) == INSN
  1563.      && GET_CODE (PATTERN (last_insn)) == CLOBBER)
  1564.     last_insn = PREV_INSN (last_insn);
  1565.   /* We should have found the preceding compare.  */
  1566.   if (last_insn == 0 || GET_CODE (last_insn) != INSN)
  1567.     abort ();
  1568.   last_pat = PATTERN (last_insn);
  1569.   if (GET_CODE (last_pat) != SET
  1570.       || GET_CODE (SET_DEST (last_pat)) != CC0)
  1571.     abort ();
  1572.  
  1573.   /* Turn off that previous insn, now that we have got the data out of it.  */
  1574.   PUT_CODE (last_insn, NOTE);
  1575.   NOTE_LINE_NUMBER (last_insn) = NOTE_INSN_DELETED;
  1576.  
  1577.   /* Emit one replacement insn to compare operands and store result.  */
  1578.   emit_insn (gen_rtx (SET, VOIDmode, operands[0],
  1579.               gen_rtx (code, mode, SET_SRC (last_pat), const0_rtx)));
  1580. }
  1581.  
  1582. /* Output reasonable peephole for set-on-condition-code insns.
  1583.    Note that these insns assume a particular way of defining
  1584.    labels.  Therefore, *both* tm-sparc.h and this function must
  1585.    be changed if a new syntax is needed.  */
  1586.  
  1587. char *
  1588. output_scc_insn (code, operand)
  1589.      enum rtx_code code;
  1590.      rtx operand;
  1591. {
  1592.   rtx xoperands[2];
  1593.   rtx label = gen_label_rtx ();
  1594.   int cc_in_fccr = cc_status.flags & CC_IN_FCCR;
  1595.   int antisymmetric = 0;
  1596.  
  1597.   xoperands[0] = operand;
  1598.   xoperands[1] = label;
  1599.  
  1600.   switch (code)
  1601.     {
  1602.     case NE:
  1603.       if (cc_in_fccr)
  1604.     output_asm_insn ("fbne,a %l0", &label);
  1605.       else
  1606.     output_asm_insn ("bne,a %l0", &label);
  1607.       break;
  1608.     case EQ:
  1609.       if (cc_in_fccr)
  1610.     output_asm_insn ("fbe,a %l0", &label);
  1611.       else
  1612.     output_asm_insn ("be,a %l0", &label);
  1613.       break;
  1614.     case GE:
  1615.       if (cc_in_fccr)
  1616.     output_asm_insn ("fbge,a %l0", &label);
  1617.       else
  1618.     output_asm_insn ("bge,a %l0", &label);
  1619.       antisymmetric = 1;
  1620.       break;
  1621.     case GT:
  1622.       if (cc_in_fccr)
  1623.     output_asm_insn ("fbg,a %l0", &label);
  1624.       else
  1625.     output_asm_insn ("bg,a %l0", &label);
  1626.       antisymmetric = 1;
  1627.       break;
  1628.     case LE:
  1629.       if (cc_in_fccr)
  1630.     output_asm_insn ("fble,a %l0", &label);
  1631.       else
  1632.     output_asm_insn ("ble,a %l0", &label);
  1633.       antisymmetric = 1;
  1634.       break;
  1635.     case LT:
  1636.       if (cc_in_fccr)
  1637.     output_asm_insn ("fbl,a %l0", &label);
  1638.       else
  1639.     output_asm_insn ("bl,a %l0", &label);
  1640.       antisymmetric = 1;
  1641.       break;
  1642.     case GEU:
  1643.       if (cc_in_fccr)
  1644.     abort ();
  1645.       else
  1646.     output_asm_insn ("bgeu,a %l0", &label);
  1647.       antisymmetric = 1;
  1648.       break;
  1649.     case GTU:
  1650.       if (cc_in_fccr)
  1651.     abort ();
  1652.       else
  1653.     output_asm_insn ("bgu,a %l0", &label);
  1654.       antisymmetric = 1;
  1655.       break;
  1656.     case LEU:
  1657.       if (cc_in_fccr)
  1658.     abort ();
  1659.       else
  1660.     output_asm_insn ("bleu,a %l0", &label);
  1661.       antisymmetric = 1;
  1662.       break;
  1663.     case LTU:
  1664.       if (cc_in_fccr)
  1665.     abort ();
  1666.       else
  1667.     output_asm_insn ("blu,a %l0", &label);
  1668.       antisymmetric = 1;
  1669.       break;
  1670.     default:
  1671.       abort ();
  1672.     }
  1673.   if (antisymmetric
  1674.       && (cc_status.flags & CC_REVERSED))
  1675.     output_asm_insn ("orcc %%g0,0,%0\n\torcc %%g0,1,%0\n%l1:", xoperands);
  1676.   else
  1677.     output_asm_insn ("orcc %%g0,1,%0\n\torcc %%g0,0,%0\n%l1:", xoperands);
  1678.   return "";
  1679. }
  1680.  
  1681. /* Output a delayed branch insn with the delay insn in its
  1682.    branch slot.  The delayed branch insn template is in TEMPLATE,
  1683.    with operands OPERANDS.  The insn in its delay slot is INSN.
  1684.  
  1685.    As a special case, since we know that all memory transfers are via
  1686.    ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
  1687.    reference around the branch as
  1688.  
  1689.     sethi %hi(x),%%g1
  1690.     b ...
  1691.     ld/st [%g1+%lo(x)],...
  1692.  
  1693.    As another special case, we handle loading (SYMBOL_REF ...) and
  1694.    other large constants around branches as well:
  1695.  
  1696.     sethi %hi(x),%0
  1697.     b ...
  1698.     or %0,%lo(x),%1
  1699.  
  1700.    */
  1701.  
  1702. char *
  1703. output_delayed_branch (template, operands, insn)
  1704.      char *template;
  1705.      rtx *operands;
  1706.      rtx insn;
  1707. {
  1708.   extern rtx recog_operand[];
  1709.   rtx src = XVECEXP (PATTERN (insn), 0, 1);
  1710.   rtx dest = XVECEXP (PATTERN (insn), 0, 0);
  1711.  
  1712.   if (GET_CODE (src) == SYMBOL_REF
  1713.       || (GET_CODE (src) == CONST_INT
  1714.       && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0)))
  1715.     {
  1716.       rtx xoperands[2];
  1717.       xoperands[0] = dest;
  1718.       xoperands[1] = src;
  1719.  
  1720.       /* Output the `sethi' insn.  */
  1721.       output_asm_insn ("sethi %%hi(%1),%0", xoperands);
  1722.  
  1723.       /* Output the branch instruction next.  */
  1724.       output_asm_insn (template, operands);
  1725.  
  1726.       /* Now output the `or' insn.  */
  1727.       output_asm_insn ("or %0,%%lo(%1),%0", xoperands);
  1728.     }
  1729.   else if ((GET_CODE (src) == MEM
  1730.         && CONSTANT_ADDRESS_P (XEXP (src, 0)))
  1731.        || (GET_CODE (dest) == MEM
  1732.            && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
  1733.     {
  1734.       rtx xoperands[2];
  1735.       char *split_template;
  1736.       xoperands[0] = dest;
  1737.       xoperands[1] = src;
  1738.  
  1739.       /* Output the `sethi' insn.  */
  1740.       if (GET_CODE (src) == MEM)
  1741.     {
  1742.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1743.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  1744.         output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands);
  1745.       split_template = "ld [%%g1+%%lo(%m1)],%0";
  1746.     }
  1747.       else
  1748.     {
  1749.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1750.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  1751.         output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands);
  1752.       split_template = "st %r1,[%%g1+%%lo(%m0)]";
  1753.     }
  1754.  
  1755.       /* Output the branch instruction next.  */
  1756.       output_asm_insn (template, operands);
  1757.  
  1758.       /* Now output the load or store.
  1759.      No need to do a CC_STATUS_INIT, because we are branching anyway.  */
  1760.       output_asm_insn (split_template, xoperands);
  1761.     }
  1762.   else
  1763.     {
  1764.       extern char *insn_template[];
  1765.       extern char *(*insn_outfun[])();
  1766.       int insn_code_number;
  1767.       rtx pat = gen_rtx (SET, VOIDmode, dest, src);
  1768.       rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
  1769.       int i;
  1770.       extern rtx alter_subreg();
  1771.       extern int insn_n_operands[];
  1772.  
  1773.       /* Output the branch instruction first.  */
  1774.       output_asm_insn (template, operands);
  1775.  
  1776.       /* Now recognize the insn which we put in its delay slot.
  1777.      We must do this after outputing the branch insn,
  1778.      since operands may just be a pointer to `recog_operand'.  */
  1779.       insn_code_number = recog (pat, delay_insn);
  1780.       if (insn_code_number == -1)
  1781.     abort ();
  1782.  
  1783.       for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1784.     {
  1785.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1786.         recog_operand[i] = alter_subreg (recog_operand[i]);
  1787.     }
  1788.  
  1789.       /* Now get the template for what this insn would
  1790.      have been, without the branch.  Its operands are
  1791.      exactly the same as they would be, so we don't
  1792.      need to do an insn_extract.  */
  1793.       template = insn_template[insn_code_number];
  1794.       if (template == 0)
  1795.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1796.       output_asm_insn (template, recog_operand);
  1797.     }
  1798.   CC_STATUS_INIT;
  1799.   return "";
  1800. }
  1801.  
  1802. /* Output a newly constructed insn DELAY_INSN.  */
  1803. char *
  1804. output_delay_insn (delay_insn)
  1805.      rtx delay_insn;
  1806. {
  1807.   char *template;
  1808.   extern rtx recog_operand[];
  1809.   extern char call_used_regs[];
  1810.   extern char *insn_template[];
  1811.   extern int insn_n_operands[];
  1812.   extern char *(*insn_outfun[])();
  1813.   extern rtx alter_subreg();
  1814.   int insn_code_number;
  1815.   extern int insn_n_operands[];
  1816.   int i;
  1817.  
  1818.   /* Now recognize the insn which we put in its delay slot.
  1819.      We must do this after outputing the branch insn,
  1820.      since operands may just be a pointer to `recog_operand'.  */
  1821.   insn_code_number = recog_memoized (delay_insn);
  1822.   if (insn_code_number == -1)
  1823.     abort ();
  1824.  
  1825.   /* Extract the operands of this delay insn.  */
  1826.   INSN_CODE (delay_insn) = insn_code_number;
  1827.   insn_extract (delay_insn);
  1828.  
  1829.   /* It is possible that this insn has not been properly scaned by final
  1830.      yet.  If this insn's operands don't appear in the peephole's
  1831.      actual operands, then they won't be fixed up by final, so we
  1832.      make sure they get fixed up here.  -- This is a kludge.  */
  1833.   for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1834.     {
  1835.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1836.     recog_operand[i] = alter_subreg (recog_operand[i]);
  1837.     }
  1838.  
  1839. #ifdef REGISTER_CONSTRAINTS
  1840.   if (! constrain_operands (insn_code_number))
  1841.     abort ();
  1842. #endif
  1843.  
  1844.   cc_prev_status = cc_status;
  1845.  
  1846.   /* Update `cc_status' for this instruction.
  1847.      The instruction's output routine may change it further.
  1848.      If the output routine for a jump insn needs to depend
  1849.      on the cc status, it should look at cc_prev_status.  */
  1850.  
  1851.   NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
  1852.  
  1853.   /* Now get the template for what this insn would
  1854.      have been, without the branch.  */
  1855.  
  1856.   template = insn_template[insn_code_number];
  1857.   if (template == 0)
  1858.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1859.   output_asm_insn (template, recog_operand);
  1860.   return "";
  1861. }
  1862.  
  1863. /* Output the insn HEAD, keeping OPERANDS protected (wherever they are).
  1864.    HEAD comes from the target of some branch, so before we output it,
  1865.    we delete it from the target, lest we execute it twice.  The caller
  1866.    of this function promises that such code motion is permissable.  */
  1867. char *
  1868. output_eager_then_insn (head, operands)
  1869.      rtx head;
  1870.      rtx *operands;
  1871. {
  1872.   extern rtx alter_subreg ();
  1873.   extern int insn_n_operands[];
  1874.   extern rtx recog_operand[];
  1875.   rtx xoperands[MAX_RECOG_OPERANDS];
  1876.   int insn_code_number, i, nbytes;
  1877.   rtx nhead;
  1878.  
  1879.   /* Micro-hack: run peephole on head if it looks like a good idea.
  1880.      Right now there's only one such case worth doing...
  1881.  
  1882.      This could be made smarter if the peephole for ``2-insn combine''
  1883.      were also made smarter.  */
  1884.   if (GET_CODE (PATTERN (head)) == SET
  1885.       && REG_P (SET_SRC (PATTERN (head)))
  1886.       && REG_P (SET_DEST (PATTERN (head)))
  1887.       && (nhead = next_real_insn_no_labels (head))
  1888.       && GET_CODE (nhead) == INSN
  1889.       && GET_CODE (PATTERN (nhead)) == SET
  1890.       && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0
  1891.       && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head))
  1892.       || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head))))
  1893.     /* Something's wrong if this does not fly.  */
  1894.     if (! peephole (head))
  1895.       abort ();
  1896.  
  1897.   /* Save our contents of `operands', since output_delay_insn sets them.  */
  1898.   insn_code_number = recog_memoized (head);
  1899.   nbytes = insn_n_operands[insn_code_number] * sizeof (rtx);
  1900.   bcopy (operands, xoperands, nbytes);
  1901.  
  1902.   /* Output the delay insn, and prevent duplication later.  */
  1903.   delete_insn (head);
  1904.   output_delay_insn (head);
  1905.  
  1906.   /* Restore this insn's operands.  */
  1907.   bcopy (xoperands, operands, nbytes);
  1908. }
  1909.  
  1910. /* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;
  1911.    or 0, if there is none.  Also return 0 if we cross a label.  */
  1912.  
  1913. rtx
  1914. next_real_insn_no_labels (label)
  1915.      rtx label;
  1916. {
  1917.   register rtx insn = NEXT_INSN (label);
  1918.   register RTX_CODE code;
  1919.  
  1920.   while (insn)
  1921.     {
  1922.       code = GET_CODE (insn);
  1923.       if (code == INSN)
  1924.     {
  1925.       if (GET_CODE (PATTERN (insn)) != CLOBBER
  1926.           && GET_CODE (PATTERN (insn)) != USE)
  1927.         return insn;
  1928.     }
  1929.       if (code == CALL_INSN || code == JUMP_INSN)
  1930.     return insn;
  1931.       if (code == CODE_LABEL)
  1932.     return 0;
  1933.       insn = NEXT_INSN (insn);
  1934.     }
  1935.  
  1936.   return 0;
  1937. }
  1938.  
  1939. int
  1940. operands_satisfy_eager_branch_peephole (operands, conditional)
  1941.      rtx *operands;
  1942.      int conditional;
  1943. {
  1944.   rtx label;
  1945.  
  1946.   if (conditional)
  1947.     {
  1948.       if (GET_CODE (operands[0]) != IF_THEN_ELSE)
  1949.     return 0;
  1950.  
  1951.       if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF)
  1952.     label = XEXP (XEXP (operands[0], 1), 0);
  1953.       else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF)
  1954.     label = XEXP (XEXP (operands[0], 2), 0);
  1955.       else return 0;
  1956.     }
  1957.   else
  1958.     {
  1959.       label = operands[0];
  1960.     }
  1961.  
  1962.   if (LABEL_NUSES (label) == 1)
  1963.     {
  1964.       rtx prev = PREV_INSN (label);
  1965.       while (prev && GET_CODE (prev) == NOTE)
  1966.     prev = PREV_INSN (prev);
  1967.       if (prev == 0
  1968.       || GET_CODE (prev) == BARRIER)
  1969.     {
  1970.       rtx head = next_real_insn_no_labels (label);
  1971.  
  1972.       if (head
  1973.           && ! INSN_DELETED_P (head)
  1974.           && GET_CODE (head) == INSN
  1975.           && GET_CODE (PATTERN (head)) == SET
  1976.           && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
  1977.                       GET_MODE (SET_DEST (PATTERN (head))))
  1978.           && strict_single_insn_op_p (SET_DEST (PATTERN (head)),
  1979.                       GET_MODE (SET_DEST (PATTERN (head)))))
  1980.         {
  1981.           if (conditional == 2)
  1982.         return (GET_CODE (operands[1]) != PC
  1983.             && safe_insn_src_p (operands[2], VOIDmode)
  1984.             && strict_single_insn_op_p (operands[2], VOIDmode)
  1985.             && operand_clobbered_before_used_after (operands[1], label));
  1986.           return 1;
  1987.         }
  1988.     }
  1989.     }
  1990.  
  1991.   if (conditional == 1
  1992.       && GET_CODE (operands[1]) != PC
  1993.       && safe_insn_src_p (operands[2], VOIDmode)
  1994.       && strict_single_insn_op_p (operands[2], VOIDmode)
  1995.       && operand_clobbered_before_used_after (operands[1], label))
  1996.     return 1;
  1997.  
  1998.   return 0;
  1999. }
  2000.  
  2001. @
  2002.  
  2003.  
  2004. 1.2
  2005. log
  2006. @Fixed stack alignment bug.
  2007. @
  2008. text
  2009. @d844 1
  2010. a844 1
  2011.       && (XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
  2012. d847 4
  2013. a850 1
  2014.       && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) == 0) {
  2015. @
  2016.  
  2017.  
  2018. 1.1
  2019. log
  2020. @Initial revision
  2021. @
  2022. text
  2023. @d735 1
  2024. a735 1
  2025.         return "ldd %1,%0 -- 1";
  2026. d847 12
  2027. a858 1
  2028.       && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) != 0)
  2029. a868 10
  2030.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  2031.     {
  2032.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  2033.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  2034.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  2035.       cc_status.flags |= CC_KNOW_HI_G1;
  2036.       cc_status.mdep = XEXP (operands[1], 0);
  2037.       return "ldd [%%lo(%m1)+%%g1],%0";
  2038.     }
  2039.       return "ldd %1,%0 -- 2";
  2040. @
  2041.